import json
import xmltodict
import pandas as pd
from pasers.paser_utils import traverse_dir, re_filter
from tqdm import tqdm


def traverse_dict(tree,
                  shared_fields,
                  non_shared_fields,
                  dict_to_save,
                  desc_to_save):
    """_summary_
    递归遍历字典，途中
    Args:
        tree (dict): 字典
        shared_fields (dict): xml的域名对应保存表格的域名
        non_shared_fields (dict): xml的域名对应保存表格的域名
        dict_to_save (dict): 字典用来保存提取的表格数据
        desc_to_save (list): str用来保存提取的文本数据
    """
    for k, v in tree.items():
        if isinstance(v, dict):
            traverse_dict(v,
                          shared_fields,
                          non_shared_fields,
                          dict_to_save,
                          desc_to_save)
        elif k in shared_fields:
            dict_to_save[shared_fields[k]] = v
        elif k in non_shared_fields:
            dict_to_save[non_shared_fields[k]].append(v)
        else:
            include_keys = {
                '销售方纳税人识别号',
                '购买方纳税人识别号',
                '发票号码',
                '开票日期',
                '合计金额',
                '合计税额',
                '备注',
                '开票人'
            }
            new_text = f'{k}:{v}\n'
            if k in include_keys:
                desc_to_save.append(new_text)


def single_parse(file_path):
    """_summary_

    Args:
        file_path (str): xml文件路径
        df (dataframe): 转换的dataframe
    """
    with open(file_path, 'r', encoding="utf-8") as f:
        _text = f.read()
    tree = xmltodict.parse(_text)
    if 'EInvoice' not in tree:
        raise ValueError('目标XML文件不是Invoice!')

    shared_fields = dict({'SellerName': '销售方名称',
                          'SellerIdNum': '销售方纳税人识别号',
                          'BuyerName': '购买方名称',
                          'BuyerIdNum': '购买方纳税人识别号',
                          'InvoiceNumber': '发票号码',
                          'IssueTime': '开票日期',
                          'TotalAmWithoutTax': '合计金额',
                          'TotalTaxAm': '合计税额',
                          'Remark': '备注',
                          'Drawer': '开票人'})

    non_shared_fields = dict({'ItemName': '项目名称',
                              'SpecMod': '规格型号',
                              'MeaUnits': '单位',
                              'Quantity': '数量',
                              'UnPrice': '单价',
                              'Amount': '金额',
                              'TaxRate': '税额'})

    dict_to_save = dict()

    # 初始化字典
    for k, v in shared_fields.items():
        dict_to_save[v] = None
    for k, v in non_shared_fields.items():
        dict_to_save[v] = []
    desc_to_save = []
    traverse_dict(tree,
                  shared_fields,
                  non_shared_fields,
                  dict_to_save,
                  desc_to_save)
    num_row = len(dict_to_save['项目名称'])
    for k, v in dict_to_save.items():
        if not isinstance(v, list):
            dict_to_save[k] = [v] * num_row
        elif len(v) == 0 or v is None:
            dict_to_save[k] = [''] * num_row
        else:
            dict_to_save[k] = [' '.join(v)] * num_row
    data_list = pd.DataFrame(dict_to_save).to_dict(orient='records')
    desc_text = ''.join(desc_to_save)
    return data_list, desc_text


def process_xml_dicts(data_list, fp, file_uuid, desc):
    table_keys = {
        '项目名称', '规格型号', '单位', '数量', '单价', '金额', '税率/征收率', '税额', '销售方名称', '购买方名称'}
    table_info = {}
    concat_ls = [desc]
    for i, data_dict in enumerate(data_list):
        titles = ['|文件名|']
        row_data = ['|' + file_uuid + '|']
        i = 1
        for key, value in data_dict.items():
            if key in table_keys:
                titles.append(str(key).replace('|', ' '))
                row_data.append(str(value).replace('|', ' '))
                titles.append('|')
                row_data.append('|')
                i = i + 1
            else:
                concat_ls.append(f'{key}：{value}')
        table_head, row_data = [''.join(titles), '|-' * i + '|'], [''.join(row_data)]
        table_info[f'table_{i}'] = {'row_data': row_data,
                                    'table_head': table_head}
        concat_ls.append(f'<table:table_{i}>')
    return {'file_uuid': file_uuid, 'image_info': {}, 'table_info': table_info, 'file_path': fp,
            'content': re_filter('\n'.join(concat_ls))}


def parse_xml(failed_ls, file_dir, out_dir):
    file_info = traverse_dir(file_dir, ['xml'])
    if not file_info:
        return
    file_ls = []
    for fp, f_uuid in tqdm(file_info, desc='正在提取xml文件'):
        try:
            data_list, desc = single_parse(fp)
            file_dict = process_xml_dicts(data_list, fp, f_uuid, desc)
            file_ls.append(file_dict)
        except Exception as e:
            failed_ls.append({'filePath': fp, 'reason': str(e)})
    if file_ls:
        with open(out_dir + '/xml_content.json', 'w+', encoding='utf-8') as fp:
            data = {'file_num': len(file_ls), 'file_suffix': 'xml', 'file_list': file_ls}
            json.dump(data, fp, ensure_ascii=False)
